package com.xuecheng.order.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.commons.constants.OrdersConstants;
import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.dto.OrdersDto;
import com.xuecheng.commons.model.dto.PageRequest;
import com.xuecheng.commons.model.dto.RecordDto;
import com.xuecheng.commons.model.vo.*;
import com.xuecheng.commons.utils.AuthInfoHolder;
import com.xuecheng.commons.utils.BeanHelper;
import com.xuecheng.content.api.ContentClient;
import com.xuecheng.learning.api.LearningClient;
import com.xuecheng.order.config.PayTemplate;
import com.xuecheng.order.domain.Orders;
import com.xuecheng.order.domain.Payment;
import com.xuecheng.order.mapper.OrdersMapper;
import com.xuecheng.order.service.OrdersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.order.service.PaymentService;
import com.xuecheng.search.api.SearchApi;
import com.xuecheng.teaching.api.TeachingClient;
import com.xuecheng.web.exception.BusinessException;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.naming.directory.SearchControls;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-08-10
 */
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {


    @Autowired
    private SearchApi searchApi;

    // 用户下单
    @Override
    public ResponseResult createOrder(Long coursePubId) {
        // 1.获取登录用户id
        Long userId = AuthInfoHolder.getUserId();
        // 2.查询用户之前是否已支付
        LambdaQueryWrapper<Orders> qw1 = new LambdaQueryWrapper<>();
        qw1.eq(Orders::getUserId, userId);
        qw1.eq(Orders::getCoursePubId, coursePubId);
        qw1.eq(Orders::getStatus, OrdersConstants.ORDER_PAID_STATUS); // 已支付
        long count = this.count(qw1);
        if (count > 0) {
            throw new BusinessException(ErrorCode.ORDERERROR);
        }
        // 3.查询用户之前是否已下单
        LambdaQueryWrapper<Orders> qw2 = new LambdaQueryWrapper<>();
        qw2.eq(Orders::getUserId, userId);
        qw2.eq(Orders::getCoursePubId, coursePubId);
        qw2.eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS); // 初始
        Orders orders = this.getOne(qw2);
        // 4.如果已下单，直接返回订单id
        if (ObjectUtil.isNotEmpty(orders)) {
            return ResponseResult.okResult(orders.getOrderNo());
        }
        // 5.如果未下单，封装订单数据
        orders= new Orders();
        orders.setOrderNo(IdUtil.simpleUUID()); // 订单号 32位唯一字符串
        // 根据课程发布id查询课程发布信息
        ResponseResult<CoursePubIndexVo> responseResult = searchApi.findById(coursePubId.toString());
        // 判断是否存在课程信息
        if (responseResult.getCode()!=0) {
            throw new BusinessException(ErrorCode.ERROR);
        }
        CoursePubIndexVo indexVo = responseResult.getData();
        orders.setCoursePubId(coursePubId); // 课程id
        orders.setCoursePubName(indexVo.getName()); // 课程名称
        orders.setCompanyId(indexVo.getCompanyId()); // 机构id
        orders.setUserId(userId); // 用户id
        // orders.setPrice(indexVo.getPrice().longValue()); // 课程支付价格
        orders.setPrice(1L); // TODO 开发写死1分钱
        orders.setStatus(OrdersConstants.ORDER_INIT_STATUS); // 初始状态
        orders.setCreateDate(DateUtil.date());// 创建时间
        // 6.保存数据库
        this.save(orders);
        // 7.返回订单号
        return ResponseResult.okResult(orders.getOrderNo());
    }


    @Autowired
    private PayTemplate payTemplate;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private LearningClient learningClient;

    // 查询支付结果
    @Override
    @GlobalTransactional
    public ResponseResult findPay(String orderNo) {
        // 1.查询微信支付状态
        Boolean isPay = payTemplate.checkPayment(orderNo);
        // 2.判断未支付
        if (!isPay) {
            throw new BusinessException(ErrorCode.NOTPLAY);
        }
        // 3.查询订单
        LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
        qw.eq(Orders::getOrderNo, orderNo);
        Orders orders = this.getOne(qw);
        // 3.判断订单是否为初始状态
        if (orders.getStatus().equals(OrdersConstants.ORDER_INIT_STATUS)) {
            updatePayStatus(orders);
        }
        // 4.转vo
        OrdersVo vo = BeanHelper.copyProperties(orders, OrdersVo.class);
        // 5.返回vo
        return ResponseResult.okResult(vo);
    }

    // 清理超时订单
    @Override
    public void clearOrders() {
        // 查前15分钟所有未支付订单
        LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
        qw.eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS);// 初始状态
        Date oldDate = DateUtil.offsetMinute(new Date(), -15).toJdkDate(); // 15分钟前时间
        qw.lt(Orders::getCreateDate, oldDate);
        List<Orders> ordersList = this.list(qw);

        if (CollectionUtil.isNotEmpty(ordersList)) {
            // 遍历订单
            for (Orders orders : ordersList) {
                // 再次确认微信是否付款
                Boolean isPay = payTemplate.checkPayment(orders.getOrderNo());
                // 判断用户是否付款
                if (isPay) { // 用户付款了，我帮你更新订单、明细、选课数据
                    updatePayStatus(orders);
                }else{ // 用户超过15分并且没付款
                    // 先关闭微信订单
                    payTemplate.closeOrder(orders.getOrderNo());
                    // 修改订单状态600004
                    orders.setStatus(OrdersConstants.ORDER_CLOSED_STATUS);
                    this.updateById(orders);
                }
            }
        }else{
            log.info("没有超时订单。。。");
        }
    }

    // 机构的订单列表及明细
    @Override
    public ResponseResult findPage(PageRequest params, OrdersDto dto) {
        // 1.创建查询条件
        LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
        // 课程名称
        String courseName = dto.getCourseName();
        qw.like(StrUtil.isNotBlank(courseName),Orders::getCoursePubName,courseName);
        // 课程状态
        Integer status = dto.getStatus();
        qw.eq(ObjectUtil.isAllNotEmpty(status),Orders::getStatus,status);
        // 订单号
        String orderNo = dto.getOrderNo();
        qw.like(StrUtil.isNotBlank(orderNo),Orders::getOrderNo,orderNo);
        // 学号
        String userId = dto.getUserId();
        //qw.eq(StrUtil.isNotBlank(userId),Orders::getUserId,userId.toString());
        qw.eq(StrUtil.isNotBlank(userId),Orders::getUserId,userId);
        // 开始-结束时间
        String orderStart = dto.getOrderStart();
        String orderEnd = dto.getOrderEnd();
        qw.between(StrUtil.isNotBlank(orderStart)&&StrUtil.isNotBlank(orderEnd),Orders::getCreateDate,orderStart,orderEnd);
        // 2.构建分页条件
        Page<Orders> page = new Page<>(params.getPageNo(),params.getPageSize() );
        // 3.执行分页查询
        page = this.page(page, qw);
        // 4.转vo
        List<Orders> ordersList = page.getRecords();
        List<OrdersVo> ordersVos = BeanHelper.copyWithCollection(ordersList, OrdersVo.class);
        //输出到excel

        // 5. 返回分页结果
        return PageResponseResult.okResult(page.getTotal(),ordersVos);
    }

    //导出excel
    @Override
    public ResponseResult indexWrite(Long companyId) {
        // 构建条件
        LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
        qw.eq(Orders::getCompanyId,companyId);
        List<Orders> ordersList = list(qw);
        List<OrdersVo> ordersVos = BeanHelper.copyWithCollection(ordersList, OrdersVo.class);
        for (OrdersVo ordersVo : ordersVos) {
            if (ordersVo.getStatus() == 600004) {
                ordersVo.setStatu("未支付");
            } else {
                ordersVo.setStatu("已支付");
            }
        }
        String fileName = "e://财务明细.xlsx";
        getPath(ordersVos,fileName);
        return ResponseResult.okResult();
    }


    @Autowired
    private ContentClient contentClient;

    @Autowired
    private TeachingClient teachingClient;
    //分页查询用户的个人订单信息
    @Override
    public ResponseResult findByPage(PageRequest request, OrdersDto dto) {

        //查询订单
        // 1.构建分页
        Page<Orders> page = new Page<>(request.getPageNo(), request.getPageSize());
        // 2.构建条件
        LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
        qw.eq(Orders::getUserId,AuthInfoHolder.getUserId());//用户
        qw.eq(Orders::getStatus,dto.getStatus());//状态
        qw.orderByDesc(Orders::getCreateDate);
        // 3.执行分页查询
        page = this.page(page, qw);
        //获取数据
        List<Orders> ordersList = page.getRecords();

        //转VO
        List<OrderPageVo> voList =new ArrayList<>();
        if (CollectionUtil.isNotEmpty(ordersList)) {//判空
            //转VO
             voList = BeanHelper.copyWithCollection(ordersList, OrderPageVo.class);
            //遍历
            for (OrderPageVo orderPageVo : voList) {
                //补全参数
                LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Orders::getOrderNo,orderPageVo.getOrderNo());
                Orders orders = this.getOne(wrapper);
                orderPageVo.setOrderId(orders.getId());//订单ID
                ResponseResult<CoursePubVo> voResponseResult = contentClient.findById(orderPageVo.getCoursePubId());
                CoursePubVo coursePubVo = voResponseResult.getData();//课程发布信息
                orderPageVo.setInitialPrice(coursePubVo.getPrice());//定价
                orderPageVo.setContentImage(coursePubVo.getPic());//课程图片
                //远程获取课程评分
                ResponseResult<StarRankVo> starRankVoResponseResult = teachingClient.countCourseComment(orderPageVo.getCoursePubId().intValue());
                //取出vo
                StarRankVo starRankVo = starRankVoResponseResult.getData();
                //补充课程评分
                orderPageVo.setContentScore(Long.valueOf(starRankVo.getStarRank()));
            }
        }
        return PageResponseResult.okResult(page.getTotal(),voList);
    }

    // 更新订单、明细、选课状态
    private void updatePayStatus(Orders orders) {
        // 3-1 修改订单状态
        orders.setStatus(OrdersConstants.ORDER_PAID_STATUS);
        this.updateById(orders);
        // 3-2 修改订单明细状态
        // 3-2-1 先查订单明细
        LambdaQueryWrapper<Payment> payQw = new LambdaQueryWrapper<>();
        payQw.eq(Payment::getOrderNo,orders.getOrderNo() );
        // 3-2-2 修改状态
        Payment payment = paymentService.getOne(payQw);
        payment.setStatus(OrdersConstants.PAID.toString());
        paymentService.updateById(payment);
        // 3-3 保存或更新选课记录
        RecordDto dto = new RecordDto();
        dto.setUserId(orders.getUserId());
        dto.setCoursePubId(orders.getCoursePubId());
        learningClient.saveRecord(dto);
    }
    public void getPath(List<OrdersVo> ordersList, String fileName) {
        EasyExcel.write(fileName, OrdersVo.class)
                .sheet()
                .doWrite(ordersList);
    }
}
